package coreEvent

import (
	"log"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"

	"github.com/Unknwon/com"
	"smartconn.cc/liugen/audio"
	"smartconn.cc/liugen/input"
	"smartconn.cc/tosone/parsing/lib/audioMgr"
	"smartconn.cc/tosone/ra_main/PFSE"
	"smartconn.cc/tosone/ra_main/common"
	"smartconn.cc/tosone/ra_main/config"
	"smartconn.cc/tosone/ra_main/ledutil"
	"smartconn.cc/tosone/ra_main/store"
)

var recordStatus bool
var pageFeature string

func init() {
	recordStatus = false
	pageFeature = ""
}

// InitBtn 初始化按键
func InitBtn() {
	input.GetButton("home").OnLongPress(LongPushHome)
	input.GetButton("home").OnPress(func() {
		log.Println("RA got a shortpress key event.")
		ShortPushHome(true)
	})
}

// ScanPage 多次扫描页面
func ScanPage() {
	searchInterval := time.Duration(50)
	searchTimes := 15
	setStatus("currPage", "")
	audio.PlayBGM(config.Audio["scanning_page"])
	log.Println("Scanning this page's feature....")
	running := true
	go func() {
		for running {
			audio.PlayBGM(config.Audio["scanning_page_di"])
			<-time.After(time.Millisecond * 1000)
		}
	}()
	count := searchTimes
	for i := 0; i < count; i++ {
		count--
		feature := PFSE.GetFeature()
		id := PFSE.Search(feature)
		if getStatus("currBook") == "" {
			setStatus("currBook", id)
			setStatus("currPage", id)
		}
		if id == "" {
			if pageFeature == "" {
				pageFeature = feature
			} else if PFSE.Compare(pageFeature, feature) > 0 {
				pageFeature = feature
			}
			log.Printf("Last page's feature length is %d\n", len(feature))
			log.Printf("Current page's feature length is %d\n", len(pageFeature))
			<-time.After(time.Millisecond * searchInterval)
			continue
		}
		break
	}
	<-time.After(time.Millisecond * searchInterval * time.Duration(count))
	running = false
	kacha()
	<-time.After(time.Millisecond * 200) // audioMgr 不能准确的知道声音何时结束
}

func kacha() {
	channel, err := audio.PlayBGM(config.Audio["scanning_page_kacha"])
	if err != nil {
		log.Println(err)
		<-time.After(time.Millisecond * 100)
		kacha()
		return
	}
	<-channel
}

// LongPushHome 长按 home 按键
func LongPushHome() {
	log.Println("RA get key longpress event: HOME.")
	if getStatus("bookStatus") == "false" { // 当前没有书在的话不可以录音，长按无效，播放提示音
		log.Println("No book on. Please check your book is still here.")
		return
	}
	lastPageInfo = map[string]interface{}{}
	audio.StopBGM()
	pageFeature = ""
	ScanPage()
	recordStatus = false
	ToggleRecord() // 开始或者停止录音
}

// ShortPushHome 短按 home 按键
func ShortPushHome(repeatLastPage bool) {
	if recordStatus && getStatus("bookStatus") == "true" { // 如果当前当前有书并且在录音的话，短按就停止录音，接着将会对录音的结果进行索引
		if !com.IsDir(config.StoryDir) { // 检测故事文件夹是否存在
			if err := os.Mkdir(config.StoryDir, 0755); err != nil { // 建立故事文件夹
				log.Println(err)
				log.Println("Cannot create " + config.StoryDir + ".")
			}
		}
		audioPath := ToggleRecord()               // 录音文件地址
		_, audioName := filepath.Split(audioPath) // 获取录音文件的文件名
		if getStatus("currBook") == "" {          // 当前书没有任何信息，添加一个封面
			log.Println("RA cannot find this book. Now add a new book.")
			bookid := common.UUID()                      // 添加封面
			topDir := path.Join(config.StoryDir, bookid) // 创建故事的顶级目录
			setStatus("currBook", bookid)
			setStatus("currPage", bookid)
			if err := os.Mkdir(topDir, 0755); err != nil { // 创建故事的主路径
				log.Println(err)
				log.Println("Cannot create path for this new story.")
				return
			}
			log.Println("Success create path for this new story.")
			store.SetBook(map[string]string{
				"bookID":       bookid,
				"serverBookID": "",
				"feature":      pageFeature,
				"version":      "",
				"isDefault":    "false",
				"title":        "",
			})
			if err := os.Mkdir(path.Join(topDir, store.GetCurrRole()), 0755); err != nil { // 创建当前角色的一个子目录
				log.Println(err)
				log.Println("Cannot create path for this role in new story.")
				return
			}
			log.Println("Success create path for this role in new story.")
			slaveDB, err = store.OpenStory(topDir)
			if err != nil {
				log.Println(err)
				return
			}
			lastPageInfo = map[string]interface{}{
				"pageID":       bookid,
				"serverPageID": "",
				"feature":      pageFeature,
				"role":         store.GetCurrRole(),
				"manifest":     changext(audioName),
			}
			slaveDB.SetPage(lastPageInfo)
			if err := copyConvert(audioPath, path.Join(topDir, store.GetCurrRole(), changext(audioName))); err != nil { // 转移录音文件
				log.Println(err)
				return
			}
		} else { // 当前书有封面信息，更新其中某一页
			topDir := path.Join(config.StoryDir, getStatus("currBook")) // 故事的顶级目录
			if getStatus("currPage") != "" {                            // 这一页找到了，添加一个新的版本页
				log.Println("I have found this page in my database. Now add a new version for this page.")
				pageInfo := slaveDB.GetPage(getStatus("currPage"), store.GetCurrRole())
				if len(pageInfo) != 0 { // 当前角色录过这一页
					log.Println("But this role have recorded this page. Now replace it.")
					lastPageInfo = map[string]interface{}{
						"pageID":       getStatus("currPage"),
						"serverPageID": "",
						"feature":      pageFeature,
						"role":         store.GetCurrRole(),
						"manifest":     changext(audioName),
					}
					slaveDB.UpdatePage(lastPageInfo)
					willRemoveAudio := path.Join(topDir, store.GetCurrRole(), pageInfo["audio"].(string))
					if com.IsFile(willRemoveAudio) {
						if err := os.Remove(willRemoveAudio); err != nil {
							log.Println(err)
							log.Printf("Cannot remove audioFile: %s\n", pageInfo["audio"].(string))
						}
					}
					if err := copyConvert(audioPath, path.Join(topDir, store.GetCurrRole(), changext(audioName))); err != nil {
						log.Println(err)
						return
					}
				} else { // 当前角色没有录过这一页
					log.Println("This role have never recorded this page.")
					log.Println("But this role have recorded this page. Now replace it.")
					lastPageInfo = map[string]interface{}{
						"pageID":       getStatus("currPage"),
						"serverPageID": "",
						"feature":      pageFeature,
						"role":         store.GetCurrRole(),
						"manifest":     changext(audioName),
					}
					slaveDB.SetPage(lastPageInfo)
					if !com.IsDir(path.Join(topDir, store.GetCurrRole())) { // 建立当前角色的一个故事文件夹
						os.Mkdir(path.Join(topDir, store.GetCurrRole()), 0755)
					}
					if err := copyConvert(audioPath, path.Join(topDir, store.GetCurrRole(), changext(audioName))); err != nil {
						log.Println(err)
						return
					}
				}
				if len(slaveDB.GetPage(getStatus("currPage"), "default")) == 0 { // 没有官方的版本
					slaveDB.SetPage(lastPageInfo)
					PFSE.AddFeature(common.FeatureWithID{ID: getStatus("currPage"), Feature: pageFeature})
				}
			} else { // 多次寻找之后，仍然没有结果，创建新页
				log.Println("After try for find this page many times but failed. Now create a new page.")
				PFSE.AddFeature(common.FeatureWithID{ID: getStatus("currPage"), Feature: pageFeature})
				pageID := common.UUID()
				lastPageInfo = map[string]interface{}{
					"pageID":       pageID,
					"feature":      pageFeature,
					"serverPageID": "",
					"role":         store.GetCurrRole(),
					"manifest":     changext(audioName),
				}
				setStatus("currPage", pageID)
				slaveDB.SetPage(lastPageInfo)
				storyDir := path.Join(topDir, store.GetCurrRole())
				if !com.IsDir(storyDir) {
					if err := os.Mkdir(storyDir, 0755); err != nil {
						log.Println(err)
						log.Println("Cannot mkdir " + storyDir)
						return
					}
				}
				if err := copyConvert(audioPath, path.Join(topDir, store.GetCurrRole(), changext(audioName))); err != nil {
					log.Println(err)
					return
				}
				log.Println("Success create a new page.")
			}
		}
	} else if getStatus("bookStatus") == "true" && repeatLastPage { // 当前有书，但是没有在录音，把当前一页的音频重新播放一次
		RestorePage() // 具体是否可以将当前页的音频重新播放这里不关心
	}
}

var audioName string

// ToggleRecord 开始停止录音
func ToggleRecord() string {
	if recordStatus { // 停止录音
		ledutil.Close()
		recordStatus = false
		log.Println("stop record.")
		audioMgr.StopRecord()
		return audioName
	}
	if audio.IsRecording() {
		audioMgr.StopRecord()
	}
	recordStatus = true
	log.Println("start record.")
	ledutil.Red()
	var err error
	audioName, err = audioMgr.RecordToPath("/tmp") // 开始录音
	if err != nil {
		log.Println(err)
	}
	return audioName
}

func copyConvert(src, dest string) error {
	if err := audio.Convert(src, dest); err != nil { // 转移录音文件
		log.Println("Cannot convert this to ogg.")
		return err
	}
	audio.PlayBGM(dest)
	if err := os.Remove(src); err != nil {
		log.Println(err)
		log.Println("Cannot remove the tmp file. Ignore this error.")
	}
	return nil
}

func changext(filename string) string {
	return strings.Split(filename, ".")[0] + ".ogg"
}
